package com.zwps.common.controller.interceptor;

import com.zwps.common.api.model.vo.LoginUserVO;
import com.zwps.common.controller.annotation.Record;
import com.zwps.common.controller.constant.HttpHeaderConstant;
import com.zwps.common.controller.tool.IPTool;
import com.zwps.common.core.context.LoginInfoContext;
import com.zwps.common.core.context.RecordAPILogContext;
import com.zwps.common.core.enums.LogTypeEnum;
import com.zwps.common.core.enums.OperateStatusEnum;
import com.zwps.common.core.enums.OperateTypeEnum;
import com.zwps.common.core.service.LogService;
import com.zwps.common.core.tool.AutowiredBeanTool;
import com.zwps.extra.http.LogAPIMessage;

import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.ContentCachingRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class APILogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Record record = handlerMethod.getMethodAnnotation(Record.class);
        if (record != null && !record.record()) {
            return true;
        }
        LogAPIMessage message = new LogAPIMessage();
        message.setRequestId(HttpHeaderConstant.getAndSetRequestId(request));
        RecordAPILogContext.setRequestLog(message);
        try {
            LoginUserVO currentUser = LoginInfoContext.getLoginInfo().getUser();
            // 设置操作用户id
            message.setOperateUserId(currentUser.getId());
            // 设置操作用户名称
            message.setOperateRealname(currentUser.getRealname());
        } catch (Exception e) {
        }
        message.setExternal(0);
        message.setOperateIp(IPTool.getIP(request));
        message.setRequestUrl(request.getRequestURI());
        message.setRequestMethod(request.getMethod());
        message.setRequestContentType(request.getContentType());
        if (record != null) {
            message.setLogType(record.logType().getCode());
            message.setOperateType(record.OperateType().getCode());
        } else {
            message.setLogType(LogTypeEnum.OPERATE.getCode());
            message.setOperateType(OperateTypeEnum.other.getCode());
        }
        message.setRequestParam(request.getQueryString());
        message.setRequestTime(System.currentTimeMillis());
        Operation operation = handlerMethod.getMethodAnnotation(Operation.class);
        if (operation != null) {
            message.setOperateName(operation.summary());
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e)
            throws Exception {
        try {

            LogAPIMessage message = RecordAPILogContext.getRequestLog();
            if (message == null) {
                return;
            }
            if (request instanceof ContentCachingRequestWrapper) {
                ContentCachingRequestWrapper requetWrapper = (ContentCachingRequestWrapper) request;
                byte[] bytes = requetWrapper.getContentAsByteArray();
                if (bytes.length > 1) {
                    message.setRequestBody(new String(bytes));
                }
            }
            message.setResponseContentType(response.getContentType());
            message.setResponseTime(System.currentTimeMillis());
            if (message.getExceptionDetail() == null) {
                message.setOperateStatus(OperateStatusEnum.SUCCESS.getCode());
            } else {
                message.setOperateStatus(OperateStatusEnum.FAIL.getCode());
            }
            message.setCostTime(message.getResponseTime() - message.getRequestTime());
            LogService logService = AutowiredBeanTool.getBean(LogService.class);
            if (logService != null) {
                logService.sendLogMessage(message);
            }
        } catch (Exception e1) {
            log.error("Unexpected error in ", e1);
        } finally {
            RecordAPILogContext.clear();
        }
    }
}
